package cn.iocoder.yudao.module.picturebook.service.bigplan;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.picturebook.controller.admin.plan.vo.PlanSaveReqVO;
import cn.iocoder.yudao.module.picturebook.dal.dataobject.book.BookDO;
import cn.iocoder.yudao.module.picturebook.dal.dataobject.plan.PlanDO;
import cn.iocoder.yudao.module.picturebook.dal.mysql.book.BookMapper;
import cn.iocoder.yudao.module.picturebook.dal.mysql.plan.PlanMapper;
import cn.iocoder.yudao.module.picturebook.service.plan.PlanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.picturebook.controller.admin.bigplan.vo.*;
import cn.iocoder.yudao.module.picturebook.dal.dataobject.bigplan.BigplanDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.picturebook.dal.mysql.bigplan.BigplanMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.picturebook.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.picturebook.service.bigplan.ReadingPlanAlgorithm.generateReadingPlan;

/**
 * 大计划表	 Service 实现类
 *
 * @author 芋道源码
 */
@Slf4j
@Service
@Validated
public class BigplanServiceImpl implements BigplanService {

    @Resource
    private BigplanMapper bigplanMapper;
    @Resource
    private PlanService planService;
    @Resource
    private BookMapper bookMapper;
    @Resource
    private PlanMapper planMapper;

    // ... existing code ...

    /**
     * 创建大计划
     *
     * @param createReqVO 大计划保存请求对象，包含大计划的相关信息
     * @param userId      用户ID，用于记录谁创建了大计划
     * @return 返回新创建的大计划ID
     */
    @Override
    public Integer createBigplan(BigplanSaveReqVO createReqVO, Integer userId) {
        // 参数校验
        if (createReqVO == null) {
            log.warn("[createBigplan][请求参数不能为空]");
            return null;
        }
        if (userId == null) {
            log.warn("[createBigplan][用户ID不能为空]");
            return null;
        }

        // 插入大计
        BigplanDO bigplan = BeanUtils.toBean(createReqVO, BigplanDO.class);
        bigplan.setCreator(userId.toString());

        Integer bigPlanId;
        int attempts = 0;
        do {
            bigPlanId = new Random().nextInt(900000) + 100000;
            attempts++;
            if (attempts > 100) { // 防止无限循环
                log.error("[createBigplan][生成唯一大计划ID失败]");
                return null;
            }
        } while (bigplanMapper.selectById(bigPlanId) != null);

        bigplan.setBigPlanId(bigPlanId);

        try {
            bigplanMapper.insert(bigplan);
        } catch (Exception e) {
            log.error("[createBigplan][插入大计失败，ID：{}]", bigPlanId, e);
            return null;
        }

        List<List<Integer>> planContent = createReqVO.getPlanContent();
        if (planContent == null) {
            return bigPlanId;
        }

        LocalDate now = LocalDate.now();

        for (int i = 0; i < planContent.size(); i++) {
            PlanSaveReqVO planSaveReqVO = new PlanSaveReqVO();
            List<Integer> planBook = planContent.get(i);
            if (planBook != null) {
                String planBookJson = planBook.toString(); // 建议替换为 JSON.toJSONString(planBook);
                planSaveReqVO.setPlanBook(planBookJson);
                planSaveReqVO.setBigPlanId(bigPlanId);
                planSaveReqVO.setPlanTime(now.plusDays(i));
                try {
                    planService.createPlan(planSaveReqVO);
                } catch (Exception e) {
                    log.error("[createBigplan][创建计划失败，大计划ID：{}，索引：{}]", bigPlanId, i, e);
                }
            }
        }

        return bigPlanId;
    }


    @Override
    public void updateBigplan(BigplanSaveReqVO updateReqVO) {
        // 参数校验
        if (updateReqVO == null) {
            log.warn("[updateBigplan][请求参数不能为空]");
            return;
        }
        if (updateReqVO.getBigPlanId() == null) {
            log.warn("[updateBigplan][大计划ID不能为空]");
            return;
        }

        // 校验存在
        if (bigplanMapper.selectById(updateReqVO.getBigPlanId()) == null) {
            log.warn("[updateBigplan][大计划不存在，ID：{}]", updateReqVO.getBigPlanId());
            return;
        }
        // 更新
        BigplanDO updateObj = BeanUtils.toBean(updateReqVO, BigplanDO.class);
        bigplanMapper.updateById(updateObj);
    }

    @Override
    public void deleteBigplan(Integer id) {
        // 参数校验
        if (id == null) {
            log.warn("[deleteBigplan][大计划ID不能为空]");
            return;
        }

        // 校验存在
        if (bigplanMapper.selectById(id) == null) {
            log.warn("[deleteBigplan][大计划不存在，ID：{}]", id);
            return;
        }
        //先根据digid删除plan中的计划
        try {
            planService.deletePlanByBigPlanId(id);
        } catch (Exception e) {
            log.error("[deleteBigplan][删除计划失败，大计划ID：{}]", id, e);
        }
        // 删除
        bigplanMapper.deleteByBigId(id);
    }

    @Override
    public void deleteBigplanListByIds(List<Integer> ids) {
        // 参数校验
        if (ids == null || ids.isEmpty()) {
            log.warn("[deleteBigplanListByIds][大计划ID列表不能为空]");
            return;
        }

        // 删除
        bigplanMapper.deleteByIds(ids);
    }

    /**
     * 根据ID获取大计划详情
     * <p>
     * 本方法首先通过ID从数据库中查询大计划详情（BigplanDO）如果查询结果为空，则返回一个空列表
     * 接着，调用计划服务（planService）根据大计划ID获取计划内容（planContent），如果计划内容为空，则将其设置为一个空列表
     * 然后，将查询到的大计划详情转换为响应对象（BigplanRespVO），并设置其计划内容
     * 最后，将包含大计划详情及其内容的响应对象放入一个单元素列表中并返回
     *
     * @param id 大计划的ID，用于查询特定的大计划详情
     * @return 包含大计划详情及其内容的响应对象列表如果查询结果为空或计划内容为空，则返回空列表
     */
    @Override
    public List<BigplanRespVO> getBigplan(Integer id) {
        // 参数校验
        if (id == null) {
            log.warn("[getBigplan][大计划ID不能为空]");
            return Collections.emptyList();
        }

        // 根据ID查询大计划详情
        BigplanDO bigplan = bigplanMapper.selectById(id);
        // 如果查询结果为空，返回一个空列表
        if (bigplan == null) {
            log.warn("[getBigplan][大计划不存在，ID：{}]", id);
            return Collections.emptyList();
        }

        // 根据大计划ID获取计划内容
        List<List<BookDO>> planContent = null;
        try {
            planContent = planService.getPlanByBigPlanId(id);
        } catch (Exception e) {
            log.error("[getBigplan][获取计划内容失败，大计划ID：{}]", id, e);
        }
        // 如果计划内容为空，将其设置为一个空列表
        if (planContent == null) {
            planContent = Collections.emptyList();
        }

        // 将大计划详情转换为响应对象
        BigplanRespVO bigplanRespVO = BeanUtils.toBean(bigplan, BigplanRespVO.class);
        // 设置响应对象的计划内容
        bigplanRespVO.setPlanContent(planContent);

        // 将包含大计划详情及其内容的响应对象放入一个单元素列表中并返回
        return Collections.singletonList(bigplanRespVO);
    }


    private void validateBigplanExists(Integer id) {
        // 参数校验
        if (id == null) {
            log.warn("[validateBigplanExists][大计划ID不能为空]");
            return;
        }

        if (bigplanMapper.selectById(id) == null) {
            log.warn("[validateBigplanExists][大计划不存在，ID：{}]", id);
            throw exception(BIGPLAN_NOT_EXISTS);
        }
    }


    @Override
    public PageResult<BigplanRespVO> getBigplanPage(BigplanPageReqVO pageReqVO) {
        if (pageReqVO == null) {
            log.warn("[getBigplanPage][分页请求参数不能为空]");
            return PageResult.empty();
        }

        bigplanMapper.selectPage(pageReqVO);
        return PageResult.empty(); // 暂时返回空结果，原代码返回null
    }

    /**
     * 获取用户当天的计划
     *
     * @param userId 用户ID，用于查询该用户的计划
     * @return 包含用户当天计划的CommonResult对象
     */
    @Override
    public CommonResult<List<BigplanTodayRespVO>> getDayPlan(Integer userId) {
        // 参数校验
        if (userId == null) {
            log.warn("[getDayPlan][用户ID不能为空]");
            return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), "用户ID不能为空");
        }

        try {
            // 获取当前用户的所有计划
            List<BigplanDO> bigplanList = bigplanMapper.selectBigPlans(userId);
            if (bigplanList == null) {
                bigplanList = Collections.emptyList();
            }

            log.info("用户 {} 的计划列表: {}", userId, bigplanList);

            // 构建响应数据
            List<BigplanTodayRespVO> bigplanTodayRespVOList = new ArrayList<>();
            LocalDate now = LocalDate.now();

            for (BigplanDO bigplan : bigplanList) {
                if (bigplan != null) {
                    // 根据大计划ID和当前时间获取计划中的书籍列表
                    List<BookDO> bookList = null;
                    try {
                        bookList = planService.getPlanByBigPlanIdAndTime(bigplan.getBigPlanId(), now);
                    } catch (Exception e) {
                        log.error("[getDayPlan][获取计划书籍列表失败，大计划ID：{}]", bigplan.getBigPlanId(), e);
                    }
                    // 将大计划和对应的书籍列表转换为响应对象
                    BigplanTodayRespVO vo = convertToBigplanTodayRespVO(bigplan, bookList);
                    bigplanTodayRespVOList.add(vo);
                }
            }

            return CommonResult.success(bigplanTodayRespVOList);
        } catch (Exception e) {
            log.error("获取用户 {} 的计划时发生异常", userId, e);
            return CommonResult.error(INTERNAL_SERVER_ERROR);
        }
    }

    //添加回滚事务
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean addBigplanGather(BigplanGatherRespVO reqVO, Integer userId) {
        // 参数校验
        if (reqVO == null) {
            log.warn("[addBigplanGather][请求参数不能为空]");
            return false;
        }
        if (userId == null) {
            log.warn("[addBigplanGather][用户ID不能为空]");
            return false;
        }

        try {
            //根据传来的参数创建大计划
            //获取当前计划复习类型
            Integer reviewType = reqVO.getReviewType();
            //获取当前计划每日几本新的书
            Integer dailyNew = reqVO.getDailyNew();
            //0:代表不复习，1：代表复习一次（学完第二天复习），2：复习2次（2,5），3：复习3次(2，5，8)，4：复习4次（2，5，8，16），5：复习5次（2，5，8，16，31），
            //先根据绘本集id获取所以的绘本id
            List<Long> gatherId = reqVO.getGatherId();
            if (gatherId == null || gatherId.isEmpty()) {
                log.warn("[addBigplanGather][绘本集ID列表不能为空]");
                return false;
            }

            List<BookDO> bookAllList = new ArrayList<>();
            for (Long id : gatherId) {
                if (id != null) {
                    List<BookDO> bookList = bookMapper.getByGatherId(id);
                    if (bookList != null) {
                        bookAllList.addAll(bookList);
                    }
                }
            }
            //获取所以绘本id
            List<Long> bookIdList = bookAllList.stream()
                    .filter(Objects::nonNull)
                    .map(BookDO::getId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            //对书籍中的重复id去重
            bookIdList = bookIdList.stream().distinct().collect(Collectors.toList());
            //获取当前时间
            LocalDate now = LocalDate.now();
            //现在根据参数制定计划
            Map<LocalDate, List<Long>> dateListMap = generateReadingPlan(bookIdList, dailyNew, reviewType, now);
            //创建大计划
            BigplanDO bigplan = new BigplanDO();
            int bigPlanId;
            int attempts = 0;
            do {
                bigPlanId = (new Random().nextInt(900000) + 100000);
                attempts++;
                if (attempts > 100) { // 防止无限循环
                    log.error("[addBigplanGather][生成唯一大计划ID失败]");
                    return false;
                }
            } while (bigplanMapper.selectById(bigPlanId) != null);
            bigplan.setBigPlanId(bigPlanId);
            bigplan.setPlanName(reqVO.getPlanName());
            bigplan.setTotalDay(dateListMap.size());
            bigplan.setCreator(String.valueOf(userId));
            bigplanMapper.insert(bigplan);
            //创建计划
            for (Map.Entry<LocalDate, List<Long>> entry : dateListMap.entrySet()) {
                if (entry != null && entry.getKey() != null && entry.getValue() != null) {
                    PlanDO plan = new PlanDO();
                    plan.setPlanId(new Random().nextInt(900000) + 100000);
                    plan.setBigPlanId(bigplan.getBigPlanId());
                    plan.setPlanTime(entry.getKey());
                    plan.setPlanBook(entry.getValue().stream()
                            .filter(Objects::nonNull)
                            .map(String::valueOf)
                            .collect(Collectors.joining(",")));
                    planMapper.insert(plan);
                }
            }
            return true;
        } catch (Exception e) {
            log.error("[addBigplanGather][创建大计划失败，用户ID：{}]", userId, e);
            return false;
        }
    }

    /**
     * 将 BigplanDO 和 BookDO 列表转换为 BigplanTodayRespVO
     */
    private BigplanTodayRespVO convertToBigplanTodayRespVO(BigplanDO bigplan, List<BookDO> bookList) {
        BigplanTodayRespVO vo = new BigplanTodayRespVO();
        vo.setPlanContent(bookList == null ? Collections.emptyList() : bookList);
        vo.setBigPlanId(bigplan.getBigPlanId());
        vo.setPlanName(bigplan.getPlanName());
        vo.setTotalDay(bigplan.getTotalDay());
        vo.setCreateTime(bigplan.getCreateTime());
        return vo;
    }

}